package com.example.qihuibao.utils

import com.example.qihuibao.XApplication
import com.example.qihuibao.bean.DeviceBean
import com.example.qihuibao.constant.Config
import com.github.gzuliyujiang.oaid.DeviceID
import com.google.gson.Gson
import java.io.IOException
import java.net.*


object ConnectUtil {
    private const val IP = "255.255.255.255"//广播，貌似路由器会丢掉这些数据包？
//    private const val IP = "239.255.255.255"
    private const val PORT = 65500
    private const val UDPBroadcastMessage = "i am server"

    fun sendUDPBroadcast() {
        val msg: ByteArray = UDPBroadcastMessage.toByteArray()
         //在Java UDP中单播与广播的代码是相同的,要实现具有广播功能的程序只需要使用广播地址即可, 例如：这里使用了本地的广播地址
        val inetAddr = InetAddress.getByName(IP)
        val client = DatagramSocket()
        client.send(DatagramPacket(msg, msg.size, inetAddr, PORT))
        client.disconnect()
        client.close()
    }

    fun receiveUDPBroadcast(receive:(message:String, ip:String)->Unit) {
        if (!Config.isServerStation) {
            val len = 1024
            val byteArray = ByteArray(len)
            val socket = DatagramSocket(PORT)
            val packet = DatagramPacket(byteArray, len)
            socket.receive(packet)
            val message = String(byteArray)
            val hostIp = packet.address.hostAddress
            receive(message, hostIp)
            socket.disconnect()
            socket.close()
            //返回给server
            val deviceBean = DeviceBean("${DeviceID.getAndroidID(XApplication.application)}", hostIp)
            val msg: ByteArray = "${Gson().toJson(deviceBean)}".toByteArray()
            //在Java UDP中单播与广播的代码是相同的,要实现具有广播功能的程序只需要使用广播地址即可, 例如：这里使用了本地的广播地址
            val inetAddr = InetAddress.getByName(hostIp)
            val datagramPacket = DatagramSocket()
            datagramPacket.send(DatagramPacket(msg, msg.size, inetAddr, PORT+1))
            datagramPacket.disconnect()
            datagramPacket.close()
        }else {
            val len = 1024
            val byteArray = ByteArray(len)
            val socket = DatagramSocket(PORT+1)
            val packet = DatagramPacket(byteArray, len)
            socket.receive(packet)
            val message = String(byteArray)
            val hostIp = packet.address.hostAddress
            receive(message, hostIp)
            socket.disconnect()
            socket.close()
        }
    }

    //组播(UDP)
    const val GROUP_PORT = 18611
    const val GROUP_IP = "239.0.0.3"//239.0.0.0～239.255.255.255为本地管理组播地址

    //发送组播
    fun groupSend(targetIp:String = "") {
        try {
            val deviceBean = DeviceBean(DeviceID.getAndroidID(XApplication.application), IpUtil.getHostIP(), Config.isServerStation, targetIp)
            val sendBuffer = Gson().toJson(deviceBean).toByteArray()
            val multicastSocket = MulticastSocket(GROUP_PORT)
            val inetAddress = InetAddress.getByName(GROUP_IP)
            multicastSocket.joinGroup(inetAddress)
            multicastSocket.soTimeout = 5000
            val sendPacket = DatagramPacket(sendBuffer, sendBuffer.size, inetAddress, GROUP_PORT)
//            LogUtil.e("ip$GROUP_IP:$GROUP_PORT byte$sendBuffer")
            multicastSocket.send(sendPacket)
            multicastSocket.close()
        }catch (e:Exception) {
            LogUtil.e("groupSend error:${e.message}")
        }
    }

    fun groupReceive(back:(message:String)->Unit) {
        try {
            val multicastSocket = MulticastSocket(GROUP_PORT)
            val inetAddress = InetAddress.getByName(GROUP_IP)
            multicastSocket.joinGroup(inetAddress)
            val receiveBuffer = ByteArray(1024)
            val receivePacket = DatagramPacket(receiveBuffer, receiveBuffer.size)
            multicastSocket.receive(receivePacket)
            val message = String(receivePacket.data, 0, receivePacket.length)
//            val hostIp = inetAddress.hostAddress
            back(message)
        } catch (e: Exception) {
            LogUtil.e("groupReceive error:${e.message}")
        }
    }

    fun serverGroup(received:(msg:String)->Unit, sended:(msg:String)->Unit) {
//        val multicastSocket: MulticastSocket
//        val inetAddress: InetAddress
//        try {
//            multicastSocket = MulticastSocket(PORT)
//            inetAddress = InetAddress.getByName(IP)
//            multicastSocket.joinGroup(inetAddress)
//            try {
//                multicastSocket.soTimeout = 5000
//                val sendPacket = DatagramPacket(bytesToSend, bytesToSend.size, inetAddress, PORT)
//                LogUtil.e("ip$IP:$PORT byte$bytesToSend")
//                multicastSocket.send(sendPacket)
//                multicastSocket.close()
//            } catch (e: java.lang.Exception) {
//                e.printStackTrace()
//                LogUtil.e("${e.message}")
//            }
//        } catch (e: java.lang.Exception) {
//            LogUtil.e("UdpMultiReceive: ${e.message}")
//        }
    }

    fun clientGroup(sended:(msg:String)->Unit, received:(msg:String)->Unit) {
        var info = "...."
        val PORT = 18611
        var receiveInfo: ByteArray? = null
        val IP = "239.0.0.3"
        val multicastSocket: MulticastSocket
        val inetAddress: InetAddress
        try {
            multicastSocket = MulticastSocket(PORT)
            inetAddress = InetAddress.getByName(IP)
            multicastSocket.joinGroup(inetAddress)
            try {
                while (true) {
                    val inBuf = ByteArray(1024)
                    val inPacket = DatagramPacket(inBuf, inBuf.size)
                    multicastSocket.receive(inPacket)
                    receiveInfo = inPacket.data
                    val inetAddress = inPacket.address
                    //对方Ip
                    val oppositeIp = inetAddress.hostAddress
                    LogUtil.e("我是Ip== $oppositeIp 发送过来的数据！")
                    info = String(inPacket.data, 0, inPacket.length)
                    LogUtil.e("发过来的数据为=$info")
                }
            } catch (e: SocketException) {
                e.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        } catch (e: Exception) {
            LogUtil.e("UdpMultiReceive: " + e.message)
        }
    }
}